home *** CD-ROM | disk | FTP | other *** search
- //
- // PackDisk v1.2, 9/28/90. Copyright 1990, Brad Davis.
- // Unlimited distribution of unmodified source and executable permitted.
- // bugs, suggestions, etc to bradd@gssc
- //
- // Suggested compilation for Microsoft C 6.0:
- // cl /AC /W3 /WX packdisk.c setargv /link /NOE
- //
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <process.h>
- #include <dos.h>
- #include <types.h>
- #include <stat.h>
- #include <fcntl.h>
- #include <io.h>
- #include <conio.h>
-
- typedef struct fINFO {
- char *name;
- long size;
- struct fINFO *next;
- } FINFO;
-
- typedef struct diskfree_t DISKFREE;
- typedef struct stat FILESTAT;
-
- static char *shell;
-
- //
- // Insert a new file into our list, sorting by size as we go.
- //
- void insert (
- FINFO **list,
- FINFO *new
- )
- {
- auto FINFO *cur;
- auto FINFO **prev;
-
- // Traverse the list until we find a file that is smaller.
- for (prev = list, cur = *list;
- cur;
- prev = &cur->next, cur = cur->next)
- {
- // New one is bigger than this one ?
- if (new->size > cur->size)
- {
- new->next = cur; // Yes, link small one below new
- *prev = new; // and bigger one to new one
- return;
- }
- }
-
- // At the end of the list, so append the new (and smallest) one
- *prev = new;
- new->next = 0;
- return;
- }
-
-
- //
- // Copy the files over so that wasted space is minimized
- //
- int copy (
- FINFO **list,
- char *dest,
- int cluster_size,
- int avail_clusters
- )
- {
- auto FINFO *cur;
- auto FINFO **prev;
- auto int remaining;
- auto int err;
- auto int clusters;
- auto char destname[128];
-
- // Set the clusters-remaining count
- remaining = avail_clusters;
-
- // Traverse the list
- for (prev = list, cur = *list;
- cur && remaining;
- )
- {
- // Cache size of this file in clusters
- clusters = (int) ((cur->size + (cluster_size - 1)) / cluster_size);
-
- // Construct file name on destination device
- strcpy (destname, dest);
- strcat (destname, cur->name);
-
- // Is this file too big to fit on the disk at all?
- if ( clusters > avail_clusters)
- {
- printf ("Warning: %s too large (%ld) for destination media.\n",
- cur->name, cur->size);
-
- // Step to next in list
- prev = &cur->next;
- cur = cur->next;
- continue;
- }
-
- // Copy file if it will fit
- if (clusters <= remaining)
- {
- // Create the dest file to see if the directory can hold it
- err = open (destname, O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
- if (err == -1)
- {
- printf (" Root directory of disk is full (%ld bytes wasted)\n",
- (long) cluster_size * remaining);
- return (0); // Upper level should not see as an error
- }
- if (close (err) == -1)
- {
- printf ("Error creating directory entry for %s\n", cur->name);
- return (1);
- }
-
- // Copy this one over
- printf ("%8ld %s...", cur->size, cur->name);
- err = spawnlp (P_WAIT, shell, shell, "/C", "COPY", cur->name, dest,
- ">", "NUL", (char *) 0);
- if (err)
- {
- printf (" Error %d during copy\n", err);
- return (1);
- }
- printf ("\n");
-
- // Reduce clusters remaining count
- remaining -= clusters;
-
- // Now delete it from the list
- *prev = cur->next; // previous points to next
-
- // Do NOT step to the next entry
- cur = *prev;
- continue;
- } else
- {
- // Step to next in list
- prev = &cur->next;
- cur = cur->next;
- continue;
- }
- }
-
- // Let the user know if any space remains on the disk
- if (remaining)
- {
- printf ("%ld bytes remain on disk\n", (long) cluster_size * remaining);
- }
-
- return (0); // No error for now.
- }
-
-
- #ifdef DEBUG
- //
- // Print out the list in order
- //
- void printlist (
- FINFO *list,
- )
- {
- auto FINFO *cur;
-
- for (cur = list;
- cur;
- cur = cur->next)
- {
- printf ("%8ld %s\n", cur->size, cur->name);
- }
- }
- #endif
-
-
- //
- // Prompt for a new disk
- //
- int newdisk (
- int drive,
- int *cluster_size,
- int *avail_clusters
- ) // returns 0 if all is well
- {
- auto DISKFREE df;
- auto int err;
- static char *dest = "X:";
- static char *destdir = "X:\\";
- auto int key;
-
- do {
- printf ("\n\nInsert disk for %c: and hit return (or Dir/Erase/Format/Label/Shell).\n",
- drive + '@');
- key = tolower (getch ());
- *destdir = *dest = (char) (drive + '@');
- if (key == 'd') {
- err = spawnlp (P_WAIT, shell, shell, "/C", "DIR", dest, (char *) 0);
- }
- if (key == 'e') {
- err = spawnlp (P_WAIT, shell, shell, "/C", "DEL", destdir,
- (char *) 0);
- }
- if (key == 'f') {
- err = spawnlp (P_WAIT, "QFORMAT", "QFORMAT", dest, (char *) 0);
- }
- if ( (key == 'l') || (key == 'f') ) {
- err = spawnlp (P_WAIT, "LABEL", "LABEL", dest, (char *) 0);
- }
- if (key == 's') {
- err = spawnlp (P_WAIT, shell, shell, (char *) 0);
- }
- }
- while (key != '\r');
-
- // Find out how much space is available on dest
- err = _dos_getdiskfree (drive , &df);
- if (err)
- {
- return (1);
- }
-
- // Set the number of clusters for each file
- *cluster_size = df.sectors_per_cluster * df.bytes_per_sector;
- *avail_clusters = df.avail_clusters;
-
- printf (" Disk has %ld bytes free (%d x %d byte clusters)\n",
- *avail_clusters * (long) *cluster_size,
- *avail_clusters, *cluster_size);
-
- return (0);
- }
-
-
- void main (
- int argc,
- char *argv[]
- )
- {
- auto int err;
- auto FINFO *list;
- auto FINFO *files;
- auto FINFO *fptr;
- auto int drive;
- auto int file;
- auto int cluster_size;
- auto int avail_clusters;
- auto int number_files;
- auto FILESTAT filestat;
-
- // Validate the command line
- if (argc < 3
- || strlen (argv[argc - 1]) != 2
- || argv[argc - 1][1] != ':'
- || (drive = toupper(argv[argc - 1][0]) - '@') < 0
- )
- {
- printf ("PackDisk v1.2, 9/28/90. Copyright 1990, Brad Davis.\n\n");
- printf ("Usage:\n");
- printf (" packdisk file [file [...]] D:\n\n");
- printf ("Copies source files to disks in the destination drive,\n");
- printf ("using the minimum number of disks.\n\n");
- exit (0);
- }
-
- shell = getenv ("COMSPEC");
- if (!shell)
- {
- printf ("Cannot locate COMSPEC\n");
- exit (1);
- }
-
- // Determine the number of source files and allocate storage for them
- number_files = argc - 1 - 1; // 0 = our name, last = dest
-
- files = (FINFO *) malloc (sizeof (FINFO) * number_files);
- if (!files)
- {
- printf ("Error %d allocating for file list.\n", err);
- exit (1);
- }
-
- // Build a list of all files
- for (file = 0, fptr = &files[0]; file < number_files; file++, fptr++)
- {
- fptr->name = argv[file + 1];
-
- // Get info on the file
- err = stat (fptr->name, &filestat);
- if (err)
- {
- printf ("Error %d reading %s.\n", err, fptr->name);
- exit (1);
- }
- fptr->size = filestat.st_size;
- fptr->next = (FINFO *) 0;
- }
-
- // Build a list of the files sorted by size (decreasing)
- list = (FINFO *) 0;
- for (file = 0, fptr = files; file < number_files; file++, fptr++)
- {
- // Add it to our list
- insert (&list, fptr);
- }
-
- #ifdef DEBUG
- printlist (list);
- #endif
-
- while (list)
- {
- err = newdisk(drive, &cluster_size, &avail_clusters);
- if (err)
- {
- printf ("Error %d getting diskfree on drive %c:.\n",
- err, drive + '@');
- }
-
- // Copy files, return 0 if ok
- err = copy (&list, argv[argc - 1], cluster_size, avail_clusters);
- if (err)
- {
- printf ("Error %d during copying.\n", err);
- exit(1);
- }
- }
- }
-